package syscron

import (
	"context"
	"devOpsApi/common/util"
	"devOpsApi/model"
	controllers "devOpsApi/version/v1.0/controller"
	"encoding/json"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	"strconv"
	"time"
)

type CronSetting struct {
	Cycle  string `json:"cycle"`
	Value  string `json:"value"`
	Hour   string `json:"hour"`
	Minute string `json:"minute"`
}

/*
清理过期容器,根据项目最后一次运行构建时间判断
删除容器最后一次运行在30天之前,停止状态的容器
*/
func CleanOvertTimeDocker() {
	pipelineModel := model.NewPipeline()
	list := pipelineModel.ListCondition(time.Now().Add(-time.Hour * 24 * 30))
	if len(list) > 0 {
		cli := util.NewDockerCli()
		defer cli.Client.Close()
		_filters := filters.NewArgs()
		_filters.Add("status", "exited")
		_filters.Add("status", "paused")
		_filters.Add("status", "dead")
		containers, err := cli.Client.ContainerList(context.Background(), types.ContainerListOptions{
			All:     true,
			Filters: _filters,
		})
		if err != nil || len(containers) == 0 {
			return
		}
		containerList := make(map[string]bool)
		for _, v := range containers {
			containerList[v.Names[0][1:]] = true
		}
		for _, v := range list {
			containerName := v.Language + "_" + strconv.Itoa(int(v.Uid)) + "_" + strconv.Itoa(int(v.ID))
			if _, ok := containerList[containerName]; ok {
				_ = cli.Client.ContainerRemove(context.Background(), containerName, types.ContainerRemoveOptions{})
			}
		}
	}
	return
}

//定时执行任务 1分钟一次
func RunPipeline() {
	day := strconv.Itoa(time.Now().Day())              //多少号
	weekDay := strconv.Itoa(int(time.Now().Weekday())) //周几
	hour := strconv.Itoa(time.Now().Hour())            //几时
	min := strconv.Itoa(time.Now().Minute())           //几分
	//fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
	//fmt.Printf("当前%s号，星期%s，%s时%s分\r\n", day, weekDay, hour, min)

	pipelineModel := model.NewPipeline()
	list := pipelineModel.ListAllCron()
	if len(list) > 0 {
		for _, v := range list {
			if v.CronSetting != "" && v.CronSetting != "[]" {
				var cron []CronSetting
				err := json.Unmarshal([]byte(v.CronSetting.([]byte)), &cron)
				if err != nil {
					continue
				}
				if len(cron) > 0 {
					for _, setting := range cron {
						switch setting.Cycle {
						case "day":
							if setting.Hour == hour && setting.Minute == min {
								go ActionPipeline(v.ID)
							}
						case "week":
							if setting.Value == weekDay && setting.Hour == hour && setting.Minute == min {
								go ActionPipeline(v.ID)
							}
						case "month":
							if setting.Value == day && setting.Hour == hour && setting.Minute == min {
								go ActionPipeline(v.ID)
							}
						}
					}
				}
			}
		}
	}
	return
}

func ActionPipeline(id uint) {
	pipelineModel := model.NewPipeline()
	pipeline, err := pipelineModel.DetailAnyOne(id)
	if err != nil {
		return
	}
	now := time.Now()
	err = pipelineModel.UpdateFieldsAnyOne(pipeline.ID, map[string]interface{}{"last_build": now})
	if err != nil {
		return
	}
	pipelineModel.LastBuild = &now
	var Pipeline controllers.PipelineController
	runType := make(map[string]string)
	runType["type"] = "all"
	runType["position"] = ""
	Pipeline.RunPipeline(pipeline, "cron", runType)
}
